#include<iostream>
#include<stdlib.h>
#define N 19//棋盘大小设定
using namespace std;
static int qipan[N][N];//棋盘

int choice;
int play();
void show_qipan();
void init_qipan();
bool finish=false;
bool success();
bool xiaqi2();

void init_qipan()//初始化棋盘
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
{
qipan[i][j]=0;
}
}


struct qizi
{
int x,y;
int player;
};


bool success(struct qizi c)//胜利判断判断为false时分出胜负
{
int x,y,num;
int xmin,xmax,ymin,ymax,min,max;
//左右方向
num=0;
xmin=(c.y-4>0)?c.y-4:0;//左边界距离
xmax=(c.y+4<N-1)?c.y+4:N-1;//右边界距离
for(y=xmin;y<=xmax;y++)
{
if(qipan[c.x][y]==c.player&&num<5)
{
num++;
if(num==5)
return false;
}
else
num=0;
}
//上下方向
num=0;
ymin=(c.x-4>0)?c.x-4:0;//上方距离
ymax=(c.x+4<N-1)?c.x+4:N-1;//下方距离
for(x=ymin;x<=ymax;x++)
{
if(qipan[x][c.y]==c.player&&num<5)
{
num++;
if(num==5)
return false;
}
else
num=0;
}
//左上斜右下斜方向
num=0;
xmin=(c.y<4)?c.y:4;//左边到点距离
xmax=(N-1-c.y<4)?N-1-c.y:4;//右到点距离
ymin=(c.x<4)?c.x:4;//上到点距离
ymax=(N-1-c.x<4)?N-1-c.x:4;//下到点距离
min=xmin<ymin?xmin:ymin;//左上方到点距离
max=xmax<ymax?xmax:ymax;//右下方到点距离
for(x=c.x-min,y=c.y-min;x<=c.x+max;x++,y++)
{
if(qipan[x][y]==c.player&&num<5)
{
num++;
if(num==5)
return false;
}
else
num=0;
}
//右上斜左下斜方向
num=0;
xmin=(c.y<4)?c.y:4;//左边到点距离
xmax=(N-1-c.y<4)?N-1-c.y:4;//右到点距离
ymin=(c.x<4)?c.x:4;//上到点距离
ymax=(N-1-c.x<4)?N-1-c.x:4;//下到点距离
min=ymin<xmax?ymin:xmax;//右上方到点距离
max=xmin<ymax?xmin:ymax;//左下方到点距离
for(x=c.x-min,y=c.y+min;x<=c.x+max;x++,y--)
{
if(qipan[x][y]==c.player&&num<5)
{
num++;
if(num==5)
return false;
}
else
num=0;
}
return true;
}


void show_qipan()//显示棋盘
{
int i,j;
cout<<"----------------------------"<<endl;
//cout<<"  0 1 2 3 4 5 6 7"<<endl;打印列数
for(i=0;i<N;i++)
{
	//cout<<i<<" ";行数
for(j=0;j<N;j++)
{
if(qipan[i][j]==-1)
cout<<"#"<<" ";//黑子显示
else if(qipan[i][j]==1)
cout<<"0"<<" ";//白子显示
else
cout<<"+"<<" ";//空棋子
}
cout<<endl;
}
}


bool xiaqi2(struct qizi c)//判断落子合法
{
if(c.x>=0&&c.x<N&&c.y>=0&&c.y<N&&qipan[c.x][c.y]==0){
qipan[c.x][c.y]=c.player;//合法显示棋子
return true;
}
else
{
cout<<"exist a or b or beyond again input"<<endl;//不合法重新输入
return false;
}
}



struct qizi xiaqi(int z)//输入坐标
{
if(z==1)
cout<<"white chess---example 2 2"<<endl;//提示输入
else if(z==-1)
cout<<"black chess---example 8 9"<<endl;
struct qizi c;
cin>>c.x;
cin>>c.y;
c.player=z;
return c;
}



int main()
{
cout<<"|-------------------|"<<endl;//开始界面
cout<<"|1.help             |"<<endl;
cout<<"|2.game over        |"<<endl;
cout<<"|3.game start       |"<<endl;
cout<<"|___________________|"<<endl;
cin>>choice;
	switch(choice)
	{
		case 1:cout<<"五子棋分黑白双方，黑白交替下棋，先在上下、左右或斜边连成五子的一方胜利.ps游戏中途也可以用ctrl+c退出。"<<endl;
		break;
		case 2:cout<<"谢谢使用"<<endl;exit(0);
		break;
		case 3:cout<<"欢迎使用"<<endl;
		break;
	}//用户不同选择不同结果
	while(!finish)
	{
		play();
	}
return 0;
}


int play()//开始下棋
{
	init_qipan();
struct qizi w;
cout<<"game start..."<<endl;
show_qipan();
while(1)
{
do{
w=xiaqi(-1);
}while(!xiaqi2(w));//判断下棋位置是否有效
show_qipan();
if(!success(w))//判断是否胜利
{
cout<<"black win"<<endl;
cout<<"1.again game   2.exit"<<endl;//黑棋胜利结果显示 警告信息
cin>>choice;
if(choice==2)
{
	exit(0);
}
else{
	return -1;
}
}
do{
w=xiaqi(1);
}while(!xiaqi2(w));//判断下棋位置是否有效
show_qipan();
if(!success(w))//判断是否胜利
{
cout<<"white win"<<endl;
cout<<"1.again game   2.exit"<<endl;//白棋胜利结果显示 警告信息
cin>>choice;
if(choice==2)
{
	exit(0);//退出程序
}
else{
	return 1;
}
}
}
}